package com.sunxd.zstudy.designPattern;

import lombok.Data;

import java.util.concurrent.TimeUnit;

/**
 * @author: 作者名称
 * @date: 2021-10-13 16:35
 **/
@Data
public class M01_Singleton {

    private String age;

    // first
    private static final M01_Singleton INSTANCE1 = new M01_Singleton();

    public static M01_Singleton getInstance1() {
        return INSTANCE1;
    }

    // second 多线程访问有问题
    private static M01_Singleton INSTANCE2;

    public static M01_Singleton getInstance2() {
        if (INSTANCE2 == null) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE2 = new M01_Singleton();
        }
        return INSTANCE2;
    }

    // 3 效率降低
    private static M01_Singleton INSTANCE3;

    public static synchronized M01_Singleton getInstance3() {
        if (INSTANCE3 == null) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE3 = new M01_Singleton();
        }
        return INSTANCE3;
    }

    // 4 多线程有问题
    private static M01_Singleton INSTANCE4;

    public static M01_Singleton getInstance4() {
        if (INSTANCE4 == null) {
            synchronized (M01_Singleton.class) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                INSTANCE4 = new M01_Singleton();
            }
        }
        return INSTANCE4;
    }

    // 5 double check
    private static volatile M01_Singleton INSTANCE5;
    public static M01_Singleton getInstance5() {
        if (INSTANCE5 == null) {
            synchronized (M01_Singleton.class) {
                if (INSTANCE5 == null) {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE5 = new M01_Singleton();
                }
            }
        }
        return INSTANCE5;
    }

    // 6 静态内部类 JVM保证单例 加载外部类时，不会加载内部类，可以实现懒加载
    private M01_Singleton(){}
    private static class M01_SingletonStatic{
        private final static M01_Singleton INSTANCE6 = new M01_Singleton();
    }
    public static M01_Singleton getINSTANCE6(){
        return M01_SingletonStatic.INSTANCE6;
    }



    public static void main(String[] args) throws InterruptedException {
        // first
//        M01_Singleton m1 = getInstance1();
//        M01_Singleton m2 = getInstance1();
//        System.out.println(m1 == m2);

        // second
//        for (int i = 0; i < 100; i++) {
//            new Thread(() -> System.out.println(getInstance2().hashCode())).start();
//        }
//
//          5
        for (int i = 0; i < 5; i++) {

            int finalI = i;
            new Thread(() -> {
                M01_Singleton instance5 = getInstance5();
                System.out.println(Thread.currentThread().getName() + " instance before:"+instance5.getAge());
                instance5.setAge("after "+ finalI);
                System.out.println(Thread.currentThread().getName() + " instance after:"+instance5.getAge());
            },"thread:"+i).start();
            TimeUnit.SECONDS.sleep(1);
        }
    }

}
